Spring Web Flow
是Spring MVC
的扩展,它支持开发基于流程的应用程序.它将流程的定义与实现流程行为的类和视图分离开来.
在
Spring
中配置Web Flow
Spring Web Flow
是构建于Spring MVC
的基础上的,这意味着所有的流程请求都需要首先经过DispatcherServlet
.我们需要在Spring
应用上下文中配置一些Bean
来处理流程并执行请求.
首先,我们在Spring
的基础上会多使用到4个jar
包,并且会使用到flow
命名空间
配置
做好了准备工作,让我们一起来看一下配置
装配流程执行器
在Spring
配置文件中使用<flow:flow-executor>
元素创建一个流程执行器.
正如其名,流程执行器驱动流程的执行,用户进入一个流程时,流程执行器会为用户创建并启动一个流程执行实例,当流程暂停的时候(如为用户展示视图时),流程执行器会在用户执行操作后恢复流程.流程执行器只负责创建和执行流程,但它并不负责加载流程定义.这个任务由流程注册表完成
|
|
配置流程注册表
在Spring
配置文件中使用<flow:flow-register>
配置流程注册表,流程注册表的工作是加载定义并让流程执行器能够使用它们.
|
|
如果不使用通配符,这里也可以使用<flow:flow-location id="pizza" path="/WEN-INF/flows/springpizza.xml"/>
来指定流程配置文件的详细位置,当不显示指定id
时,以文件名作为id
的值
处理流程请求
在Spring MVC
的基础上,还需要一个FlowHandlerMapping
来帮助DispatcherServlet
发送流程请求给spring web flow
,在Spring
的上下文中添加如下配置
|
|
可以看到,它装配了流程注册表的引用,这样它就能知道如何将请求的URL匹配到流程上
FlowHandlerMapping
仅是对流程请求的处理,响应请求由FlowHandlerAdapter
处理,它会把响应发送的流程请求进行处理,在Spring
的上下文中添加如下配置:
|
|
这样,所有的准备工作都已经做完了!但这还不够,在定义流程前,我们先来看一下流程组件
流程组件
在Spring Web Flow
中,流程是由三个主要元素定义的:状态、转移和流程数据.
状态(state)
即流程中事件的发生地点,如果将流程比喻成公路旅行,那么状态就是路途上的城镇或风景点,一共有五种不同的状态
状态类型 | 作用 |
---|---|
行为(action) | 行为状态是流程逻辑发生的地方 |
决策(decision) | 决策状态将流程分成两个方向,它会基于流程数据的评估结果确定流程方向 |
结果(end) | 结束状态是流程的最后一站,一旦进入End状态,流程就会终止 |
子流程(subflow) | 子流程状态会在当前正在运行的流程上下文中启动一个心的流程 |
视图(view) | 视图状态会暂停流程并邀请用户参与流程 |
视图状态
视图状态用于为用户展现信息并使用户在流程中发挥作用,可以是任意Spring
支持的视图类型.在下面的示例中,id
在流程内标识这个状态,当不使用view
显示指定另一个视图名称时,它也代表视图的名称,model
指明表单所绑定的对象
行为状态
行为状态是应用程序自身在执行任务,行为状态一般会触发Spring
所管理的Bean
的一些方法并根据方法调用的执行结果转移到另一个状态.如下例,其中的evaluate
子节点代表行为状态要做的事,在此处它会找到id
为pizzaFlowActions
的bean
并执行saveOrder()
方法
决策状态
决策状态能够在流程执行时产生两个分支.决策状态将评估一个Boolean
类型的表达式,然后在两个状态中选择转移一个.可以看到,if
子节点是这个状体的核心,test
中的表达式值为true
则转移到then
指定状态,否则转移到else
指定状态
子流程状态
就像把代码逻辑分写到多个类/方法中一样,流程也将其分成一些子流程.如下例中子流程结束的<endstate>
的id
为orderCreated
,则流程将会进入到名为payment
的状态
结束状态
所有的流程均会结束,这就是结束状态要做的事情.
在流程结束后,接下来会发生什么取决于以下因素:
- 如果结束流程是一个子流程,那么调用它的流程将会从
<subflow-state>
处继续执行,<end-state>
的id
将会用作事件触发从<subflow-state>
开始的转移 - 如果
<end-state>
设置了view
属性,指定的视图将会被渲染.视图可以是相对于流程路径的视图模版,如果添加externalRedirect:
前缀话,将会重定向到流程外部的页面,如果添加flowRedirect:
将会重定向到另一个流程中 - 如果结束的流程不是子流程,也没有指定
view
属性,那这个流程只是会结束而已,浏览器最后将会加载流程的基本URl地址,当前已没有活动的流程,所以会开始一个新的流程实例
==流程可能会有不止一个结束状态,子流程的结束状态id
确定了激活的事件,所以可以通过多钟结束状态来结束子流程,从而能够在流程中触发不同的事件,即使不是在子流程中,在结束流程后也可以根据流程的执行情况进行多个页面的选择==
转移
流程中除结束状态之外的每个状态都至少需要一个转移,使用<transition>
子节点来定义,在前面可能你已经看到了他的身影.它是action-state/view-state/subflow-state
的子节点,其中id
可以是用户触发的事件,在子流程中,事件取决于子流程结束的id
,任何事件都可以使用no
来触发转移事件,当抛出异常时,可以使用on-exception
来指定异常的转移状态.
全局转移:在多个状态中都需要用到的转移,可以定义成全局转移
流程数据
定义变量
流程数据保存在变量中,而变量可以在流程的各个地方进行引用,它能够以多钟方式创建,在流程中创建变量的最简单形式就是使用<var>
元素
当然,也可以使用<evaluate>
元素计算并创建一个变量
也可以使用<set>
元素设置变量的值
后面两个特别类似,都是通过计算生成结果
流程数据的作用域
范围 | 作用域与可见性 |
---|---|
Conversation | 最高层级的流程开始创建,在最高层级的流程结束时销毁,被最高层级的流程与子流程共享 |
Flow | 当流程开始时创建,在流程结束时被销毁,只有在创建它的流程中是可见的 |
Request | 当一个请求进入流程的时候创建,在流程返回时被销毁 |
Flash | 当流程开始的时候创建,在流程结束的时候销毁,在视图状态渲染后,它也会被清除 |
View | 当进入视图状态时创建,当这个状态退出的时候销毁,只在视图状态内可见 |
当使用<var>
元素声明时,变量始终是流程作用域的,当使用<set>
或<evaluate>
的时候,作用域通过name
或result
属性的前缀指定
以上就是Spring Web Flow 的基础知识,至于Demo可以在《Spring 实战》的指定网站上下载源码,当然啦,也可以百度一下,为了方便起见,可以直接去我建的仓库克隆一下,传送门,这是Spring Web Flo
w的Demo
,不是全部的源码.